from socket import *
from threading import Thread
from dict_db import *


class HTTPHandle(Thread):
    def __init__(self, conn, addr, html):
        self.conn = conn
        self.client_address = addr
        self.html = html
        self.data_url = ("/login", "/register", "/find")
        self.db = Dict()
        super().__init__(daemon=True)

    def _close(self):
        self.db.close()
        self.conn.close()

    def run(self):
        request = self.conn.recv(1024).decode()
        if not request:
            return
        parse = self._parse_request(request)
        print(self.client_address, ":", parse)
        response = self._response(parse)
        self.conn.send(response)
        self._close()

    def _response(self, parse):
        if parse['path'] not in self.data_url:
            if parse["path"] == "/":
                page = "/login.html"
            else:
                page = parse["path"]
            return self._html_page(page)

        if parse['path'] == "/register":
            return self.do_register(parse['body'])
        if parse['path'] == "/login":
            return self.do_login(parse['body'])
        else:
            return self.do_search(parse['args'])

    def do_register(self, data):
        if self.db.register(data['user'], data['pwd2']):
            return self._html_page("/login.html")
        else:
            return self._html_page("/register.html")

    def do_login(self, data):
        if self.db.login(data['user'], data['pwd1']):
            return self._html_page("/find.html")
        else:
            return self._html_page("/login.html")

    def do_search(self, data):
        mean = self.db.search(data['word'])
        with open(self.html + "/fin_res.html", "r") as fr:
            page = fr.read()
        if mean:
            data = page % (data["word"], mean[0])
        else:
            data = page % (data["word"], "Not Found!")
        response = "HTTP/1.1 200 OK\r\n"
        response += "Content-Type:text/html\r\n"
        response += "\r\n"
        response += data
        return response.encode()

    def _html_page(self, page):
        try:
            with open(self.html + page, "rb") as fr:
                data = fr.read()
        except :
            with open(self.html + "/404.html", "rb") as fr:
                data = fr.read()
        response = b"HTTP/1.1 200 OK\r\n"
        if page[-3:] == 'css':
            response += b"Content-Type:text/css\r\n"
        else:
            response += b"Content-Type:text/html\r\n"
        response += b"\r\n"
        response += data
        return response

    def _parse_request(self, request):
        parse = {}
        lines = request.split("\n")
        tmp = lines[0].split(' ')
        parse['method'] = tmp[0]
        parse['path'] = tmp[1]
        if tmp[0] == 'POST':
            data = lines[-1].split("&")
            d_dict = {}
            for item in data:
                key, value = item.split("=")
                d_dict[key] = value
            parse["body"] = d_dict
        info = parse['path'].split("?")
        if len(info) > 1:
            data = info[1].split("&")
            d_dict = {}
            for item in data:
                key, value = item.split("=")
                d_dict[key] = value
            parse['args'] = d_dict
        parse['path'] = info[0]
        return parse


class DictServer:
    def __init__(self, host='', port=0, html=''):
        self.host = host
        self.port = port
        self.html = html
        self.address = (host, port)
        self.sock = self._create_socket()

    def _create_socket(self):
        sock = socket()
        sock.bind(self.address)
        return sock

    def serve_forever(self):
        self.sock.listen()
        print(f"------------------Listen the port {self.port}------------------")
        while True:
            try:
                conn, addr = self.sock.accept()
            except KeyboardInterrupt:
                self.sock.close()
                return
            t = HTTPHandle(conn, addr, self.html)
            t.start()


if __name__ == '__main__':
    dic = DictServer(host="0.0.0.0", port=8885, html="./")
    dic.serve_forever()
